<?php

namespace app\common\service\grammar;

use app\common\enums\AnswerStatusEnum;
use app\common\enums\CategoryStateEnum;
use app\common\enums\DetectionTypeEnum;
use app\common\service\ApiService;
use app\common\model\banxi\grammar\GrammarGrade;
use app\common\model\banxi\grammar\GrammarCategory;
use app\common\model\banxi\grammar\GrammarLearn;
use app\common\model\banxi\grammar\GrammarQuestion;
use app\common\model\banxi\grammar\GrammarDetection;
use app\common\model\banxi\grammar\GrammarDetectionAnswer;
use app\common\enums\GrammarLearnPaceEnum;
use ba\Exception;
use think\db\exception\PDOException;
use think\exception\ValidateException;
use think\facade\Cache;
use think\facade\Db;

/*
 * 语法检测
 * */
class DetectionService  extends ApiService
{

    /**
     * 获取页面基础信息
     *
     * @param int $studentId 学生ID
     * @param int $gradeId 年级ID
     * @return array
     */
    public function getPageBasicInfo($studentId, $gradeId)
    {
        $info = [
            'learnPaceValue' => 0.0,
            'lastLearnName' => ''
        ];

        // 获取该年级下所有一级语法分类
        $GrammarCategory = new GrammarCategory();
        $categoryList = $GrammarCategory->where('gradeId', $gradeId)
            ->where('level', 1)
            ->select();
        if (!$categoryList) {
            return $info;
        }
        $categoryList = $categoryList->toArray();
        // 提取分类ID列表
        $categoryIds = array_column($categoryList,'id');

        // 初始化学习进度值
        $learnPaceValue = 0.0;

        if ($categoryList) {
            // 查询学生在这些分类中的学习记录
            $GrammarLearnModel = new GrammarLearn();
            $learnList = $GrammarLearnModel->where('studentId', $studentId)
                ->whereIn('categoryId', $categoryIds)
                ->select();

            $size = count($categoryList);

            $learnPaceCountMap = [];

            // 统计不同学习进度阶段的数量
            foreach ($categoryList as $category) {
                $grammarLearn = $learnList->where('categoryId', $category['id'])->first();
                $learnPace = GrammarLearnPaceEnum::E1; // 默认学习进度

                if ($grammarLearn) {
                    $learnPace = $grammarLearn['learnPace'];
                }

                if (isset($learnPaceCountMap[$learnPace])) {
                    $learnPaceCountMap[$learnPace]++;
                } else {
                    $learnPaceCountMap[$learnPace] = 1;
                }
            }

            // 计算比例
            $learnPaceValues = $this->getAllGrammarLearnPaceConstantValues();

            $GrammarLearnPaceEnum = new GrammarLearnPaceEnum();
            foreach ($learnPaceValues as $key => $value) {
                $progress = $GrammarLearnPaceEnum->getProgress($value);
                if ($progress <= 0) {
                    continue;
                }

                $count = $learnPaceCountMap[$value] ?? 0;

                if ($count == $size) {
                    $learnPaceValue += $progress;
                } else {
                    $basicProgress = $progress / $size;
                    $learnPaceValue += round($basicProgress * $count, 1);
                }
            }
        }

        $info['learnPaceValue'] = $learnPaceValue;
//        halt($info);
        // 获取上次学习到的内容
        $grammarLearn = $this->getLearnLastByStudentIdAndCategoryIds($studentId, $categoryIds);

        if ($grammarLearn) {
            $grammarCategory = $GrammarCategory->find($grammarLearn['categoryId']);
            $info['lastLearnName'] = $grammarCategory ? $grammarCategory['name'] : '';
        }

        return $info;
    }

    /**
     * 获取学生在指定分类中最后学习的记录
     *
     * @param int $studentId 学生ID
     * @param array $categoryIds 分类ID列表
     * @return array|null
     */
    public function getLearnLastByStudentIdAndCategoryIds($studentId, $categoryIds)
    {
        return GrammarLearn::where('studentId', $studentId)
            ->whereIn('categoryId', $categoryIds)
            ->order('updateTime', 'desc') // 假设按更新时间倒序
            ->limit(1)
            ->find();
    }
    /**
     * 获取GrammarLearnPaceEnum中的所有常量
     *
     * @return array
     */
    public function getAllGrammarLearnPaceConstantValues()
    {
        //直接访问所有已知常量
        return [
            'E1' => GrammarLearnPaceEnum::E1,
            'E2' => GrammarLearnPaceEnum::E2,
            'E3' => GrammarLearnPaceEnum::E3,
            'E4' => GrammarLearnPaceEnum::E4,
            'E5' => GrammarLearnPaceEnum::E5,
            'E6' => GrammarLearnPaceEnum::E6,
        ];
    }

    /**
     * 开始检测
     *
     * @param int $studentId 学员ID
     * @param int $categoryId 分类ID
     * @param bool $isReset 是否重置
     * @return Response
     */
    public function startDetection($studentId, $categoryId, $isReset = false)
    {
        // 开启事务
        Db::startTrans();
        try {
            // 获取分类信息
            $grammarCategory = GrammarCategory::find($categoryId);
            if (!$grammarCategory) {
                throw new ValidateException('分类不存在');
            }

            if ($grammarCategory['state'] != CategoryStateEnum::E1) { // 假设1为启用状态
                throw new ValidateException('分类未启用');
            }

            // 使用Redis锁防止重复点击
            $lockKey = "grammar_detection:" . $studentId . ":" . $categoryId;
            $lockValue = uniqid();
            if (!Cache::store('redis')->set($lockKey, $lockValue, 3)) {
                throw new ValidateException('请勿重复点击');
            }

            $result = [
                'detectionId' => 0,
                'isBreak' => false
            ];

            $detectionInfo = null;

            if ($isReset) {
                // 删除检测记录
                GrammarDetection::where([
                    'studentId' => $studentId,
                    'categoryId' => $categoryId,
                    'isFinish' => 0
                ])->delete();
            } else {
                // 获取未完成的检测记录
                $detectionInfo = GrammarDetection::where([
                    'studentId' => $studentId,
                    'categoryId' => $categoryId,
                    'isFinish' => 0
                ])->find();
            }

            if ($detectionInfo) {
                $result['isBreak'] = true;
                $result['detectionId'] = $detectionInfo['id'];
            } else {
                // 生成检测记录
                $questionList = GrammarQuestion::where('categoryId', $categoryId)
                    ->order(['sortNum' => 'asc', 'id' => 'desc'])
                    ->select()
                    ->toArray();

                $detectionAnswerList = [];

                $categoryLevel = $grammarCategory['level'];

                // 创建检测记录
                $detectionInfo = new GrammarDetection();
                $detectionInfo->studentId = $studentId;
                $detectionInfo->categoryId = $categoryId;
                $detectionInfo->categoryLevel = $categoryLevel;

                if ($categoryLevel == 1) {
                    // 语法点检测 (DetectionType.E1)
                    $grammarQuestions = array_filter($questionList, function($q) {
                        return $q['detectionType'] == DetectionTypeEnum::E1;
                    });
//                    halt($grammarQuestions);
                    if (empty($grammarQuestions)) {
                        throw new ValidateException('语法点检测不存在题目，无法开始检测');
                    }

                    foreach ($grammarQuestions as $index => $grammarQuestion) {
                        $detectionAnswer = new GrammarDetectionAnswer();
                        $detectionAnswer->studentId = $studentId;
                        $detectionAnswer->questionId = $grammarQuestion['id'];
                        $detectionAnswer->serialNumber = $index + 1;
                        $detectionAnswer->detectionType = 1; // 语法点检测
                        $detectionAnswer->answerStatus = 1; // 未做
                        $detectionAnswer->testCenter = $grammarCategory['name'];
                        $detectionAnswer->questionJson = json_encode($grammarQuestion);
                        $detectionAnswerList[] = $detectionAnswer;
                    }

                    // 知识点检测 (DetectionType.E2)
                    $knowledgeQuestions = array_filter($questionList, function($q) {
                        return $q['detectionType'] == DetectionTypeEnum::E2;
                    });

                    if (empty($knowledgeQuestions)) {
                        throw new ValidateException('知识点检测不存在题目，无法开始检测');
                    }

                    foreach ($knowledgeQuestions as $index => $grammarQuestion) {
                        $detectionAnswer = new GrammarDetectionAnswer();
                        $detectionAnswer->studentId = $studentId;
                        $detectionAnswer->questionId = $grammarQuestion['id'];
                        $detectionAnswer->serialNumber = $index + 1;
                        $detectionAnswer->detectionType = 2; // 知识点检测
                        $detectionAnswer->answerStatus = 1; // 未做
                        $detectionAnswer->testCenter = $grammarCategory['name'];
                        $detectionAnswer->questionJson = json_encode($grammarQuestion);
                        $detectionAnswerList[] = $detectionAnswer;
                    }

                    $detectionInfo->totalNum = count($knowledgeQuestions);
                    $detectionInfo->totalGrammarNum = count($grammarQuestions);
                } else {
                    // 不区分检测类型的题目
                    if (empty($questionList)) {
                        throw new ValidateException('不存在题目，无法开始检测');
                    }

                    foreach ($questionList as $index => $grammarQuestion) {
                        $detectionAnswer = new GrammarDetectionAnswer();
                        $detectionAnswer->studentId = $studentId;
                        $detectionAnswer->questionId = $grammarQuestion['id'];
                        $detectionAnswer->serialNumber = $index + 1;
                        $detectionAnswer->answerStatus = 1; // 未做
                        $detectionAnswer->testCenter = $grammarCategory['name'];
                        $detectionAnswer->questionJson = json_encode($grammarQuestion);
                        $detectionAnswerList[] = $detectionAnswer;
                    }

                    $detectionInfo->total_num = count($questionList);
                }

                // 保存检测记录
                $detectionInfo->save();
                $detectionId = $detectionInfo->id;

                // 保存答题记录
                foreach ($detectionAnswerList as $detectionAnswer) {
                    $detectionAnswer->detectionId = $detectionId;
                    $detectionAnswer->save();
                }

                $result['detectionId'] = $detectionId;
            }

            // 记录学习时间
            $grammarLearn = GrammarLearn::where([
                'studentId' => $studentId,
                'categoryId' => $categoryId
            ])->find();

            if ($grammarLearn) {
                $grammarLearn->lastLearnTime = date('Y-m-d H:i:s');
                $grammarLearn->save();
            }

            // 提交事务
            Db::commit();

            // 释放锁
            if (Cache::store('redis')->get($lockKey) === $lockValue) {
                Cache::store('redis')->delete($lockKey);
            }

            return $result;
        } catch (Exception|PDOException|ValidateException $e) {
            Db::rollback();
            $this->setError($e->getMessage());
            return false;
        }
    }

    /**
     * 获取当前未做的第一题
     *
     * @param int $detectionId 检测id
     * @return Response
     */
    public function getCurrentQuestion($detectionId)
    {
        // 开启事务
        Db::startTrans();
        try {
            // 获取检测记录
            $detection = GrammarDetection::find($detectionId);
            if (!$detection) {
                throw new ValidateException('检测记录不存在');
            }

            if ($detection['isFinish']) {
                throw new ValidateException('检测已完成');
            }

            $accuracyGrammar = $detection['accuracyGrammar'];
            $categoryLevel = $detection['categoryLevel'];
            $detectionType = null;

            if ($categoryLevel == 1) {
                $detectionType = !$accuracyGrammar ? DetectionTypeEnum::E1 : DetectionTypeEnum::E2; // E1=1, E2=2
            }

            // 查询未做的第一题
            $query = GrammarDetectionAnswer::where('detectionId', $detectionId)
                ->where('answerStatus', 1) // 未做状态
                ->order('serialNumber', 'asc')
                ->limit(1);

            if ($detectionType) {
                $query->where('detectionType', $detectionType);
            }

            $detectionAnswer = $query->find();

            $result = [
                'detectionId' => 0,
                'serialNumber' => 0,
                'totalNum' => 0,
                'questionInfo' => null
            ];

            if (!$detectionAnswer) {
                return $result;
            }

            $result['detectionId'] = $detectionId;
            $result['serialNumber'] = $detectionAnswer['serialNumber'];

            if (!$detectionType) {
                $result['totalNum'] = $detection['totalNum'];
            } else {
                $result['totalNum'] = ($detectionType == 1) ? $detection['totalGrammarNum'] : $detection['totalNum'];
            }

            $result['questionInfo'] = json_decode($detectionAnswer['questionJson'], true);
            $result['questionInfo']['optionList'] = json_decode($result['questionInfo']['option'], true);
            $result['questionInfo']['answerList'] = json_decode($result['questionInfo']['answer'], true);
            return $result;
        } catch (Exception|PDOException|ValidateException $e) {
            Db::rollback();
            $this->setError($e->getMessage());
            return false;
        }
    }

    /**
     * 提交答案
     *
     * @param int $studentId 学员ID
     * @param array $answer 答案数据
     * @return array
     */
    public function submitQuestion($studentId, $answer)
    {
        Db::startTrans();
        try {
            $detectionId = $answer['detectionId'];
            $questionId = $answer['questionId'];
            $useTime = $answer['useTime'];
            $userAnswerList = $answer['userAnswerList'] ?? [];

            // 获取检测记录
            $detection = GrammarDetection::find($detectionId);
            if (!$detection) {
                throw new ValidateException('检测记录不存在');
            }

            if ($detection['isFinish']) {
                throw new ValidateException('检测已完成');
            }

            $categoryLevel = $detection['categoryLevel'];

            // 获取答题记录
            $detectionAnswer = GrammarDetectionAnswer::where([
                'detectionId' => $detectionId,
                'questionId' => $questionId
            ])->find();

            if (!$detectionAnswer) {
                throw new ValidateException('题目不存在');
            }

            if ($detectionAnswer['answerStatus'] != AnswerStatusEnum::E1) { // 1为未做状态
                throw new ValidateException('题目已答题');
            }

            $answerStatus = AnswerStatusEnum::E3; // 默认为错误 E3=3
            $grammarQuestion = json_decode($detectionAnswer['questionJson'], true);

            if (!$grammarQuestion) {
                throw new ValidateException('题目不存在');
            }

            // 判断答案是否正确
            switch ($grammarQuestion['questionType']) {
                case 1: // E1 单选题
                    if (!empty($userAnswerList) && !empty($grammarQuestion['answer']) &&
                        $userAnswerList[0] == $grammarQuestion['answer'][0]) {
                        $answerStatus = AnswerStatusEnum::E2; // 正确 E2=2
                    }
                    break;
                case 2: // E2 多选题或填空题
                    if (!empty($userAnswerList) && !empty($grammarQuestion['answer'])) {
                        $isCorrect = true;
                        foreach ($grammarQuestion['answer'] as $correctAnswer) {
                            if (!in_array($correctAnswer, $userAnswerList)) {
                                $isCorrect = false;
                                break;
                            }
                        }
                        if ($isCorrect) {
                            $answerStatus = AnswerStatusEnum::E2; // 正确 E2=2
                        }
                    }
                    break;
            }

            // 更新答题记录
            $detectionAnswer->answerStatus = $answerStatus;
            $detectionAnswer->userAnswer = json_encode($userAnswerList);
            $detectionAnswer->useTime = $useTime;
            $detectionAnswer->save();

            $result = [
                'detectionId' => $detectionId,
                'paceState' => 0,
                'accuracyGrammar' => null,
                'accuracy' => null,
                'isKnowledgeAnswer' => false
            ];

            $paceState = 0;

            // 为了兼容BUG才这样写，否则直接 = detectionAnswer.getDetectionType()即可
            $detectionType = $categoryLevel == 0 ? null : $detectionAnswer['detectionType'];
            $serialNumber = $detectionAnswer['serialNumber'];
            $submitDetection = null;

            if ($detectionType == DetectionTypeEnum::E1) { // E1 语法点检测
                if ($serialNumber >= $detection['totalGrammarNum']) {
                    // 语法点检测完毕
                    $paceState = 1;
                    $submitDetection = [
                        'detectionId' => $detectionId,
                        'detectionType' => $detectionType
                    ];
                }
            } else { // 知识点检测或其他
                if ($serialNumber >= $detection['totalNum']) {
                    // 检测完毕
                    $paceState = 2;
                    $submitDetection = [
                        'detectionId' => $detectionId,
                        'detectionType' => $detectionType
                    ];
                }
            }

            // 是否答题完毕
            if ($submitDetection != null) {
                $result = $this->submitDetection($studentId, $submitDetection);
            }

            if ($result['accuracyGrammar']==null || $result['accuracyGrammar'] >= 60) {
                $result['isKnowledgeAnswer'] = true;
            }
            $result['paceState'] = $paceState;

            Db::commit();

            return $result;
        } catch (Exception|PDOException|ValidateException $e) {
            Db::rollback();
            $this->setError($e->getMessage());
            return false;
        }
    }

    /**
     * 提交检测
     *
     * @param int $studentId 学员ID
     * @param array $p 检测数据
     * @return array
     */
    private function submitDetection($studentId, $p)
    {
        var_dump($p);
        Db::startTrans();
        try {
            $detectionId = $p['detectionId'];
            $detectionType = $p['detectionType'];

            $detection = GrammarDetection::find($detectionId);
            if (!$detection) {
                throw new ValidateException('检测记录不存在');
            }

            if ($detection['studentId'] != $studentId) {
                throw new ValidateException('检测记录不存在');
            }

            if ($detection['isFinish']) {
                throw new ValidateException('检测已完成');
            }

            $learn = GrammarLearn::where([
                'studentId' => $studentId,
                'categoryId' => $detection['categoryId']
            ])->find();

            $learnPace = $learn ? $learn['learnPace'] : 1;

            $result = [
                'detectionId' => $detectionId,
                'accuracyGrammar' => null,
                'accuracy' => null
            ];

            $currentLearnPace = 1;
            var_dump($detectionType);
            if ($detectionType == DetectionTypeEnum::E1) { // E1 语法点检测
                if ($detection['accuracyGrammar'] !== null) {
                    throw new ValidateException('语法点检测已提交，请勿重复提交');
                }

                // 计算语法正确率
                $detectionAnswerList = GrammarDetectionAnswer::where([
                    'detectionId' => $detectionId,
                    'detectionType' => $detectionType
                ])->select();

                $correctNum = 0;
                foreach ($detectionAnswerList as $answer) {
                    if ($answer['answerStatus'] == AnswerStatusEnum::E2) { // 正确
                        $correctNum++;
                    }
                }

                $accuracyGrammar = round(($correctNum / $detection['totalGrammarNum']) * 100, 4);
                $result['accuracyGrammar'] = $accuracyGrammar;
                if (!$accuracyGrammar || $accuracyGrammar >= 60) {
                    $result['isKnowledgeAnswer'] = true;
                }
                if ($result['isKnowledgeAnswer']) {
                    $currentLearnPace = 2;
                } else {
                    // 检测完成但未达标
                    $detection->isFinish = 1;
                    $detection->correctNum = 0;
                    $detection->errorNum = 0;
                    $detection->accuracy = 0;
                    $detection->useTime = array_sum(array_column($detectionAnswerList->toArray(), 'useTime'));
                    $detection->save();
                }
            } else {
                // 计算正确率
                $query = GrammarDetectionAnswer::where('detectionId', $detectionId);
                if ($detectionType !== null) {
                    $query->where('detectionType', $detectionType);
                }
                $detectionAnswerList = $query->select();

                $correctNum = 0;
                foreach ($detectionAnswerList as $answer) {
                    if ($answer['answerStatus'] == 2) { // 正确
                        $correctNum++;
                    }
                }

                $totalNum = count($detectionAnswerList);
                $accuracy = round(($correctNum / $totalNum) * 100, 4);

                $useTime = array_sum(array_column($detectionAnswerList->toArray(), 'useTime'));

                $detection->correctNum = $correctNum;
                $detection->errorNum = $totalNum - $correctNum;
                $detection->accuracy = $accuracy;
                $detection->useTime = $useTime;
                $detection->isFinish = 1;
                $detection->save();

                $result['accuracy'] = $accuracy;

                if ($accuracy <= 30) {
                    $currentLearnPace = 3;
                } else if ($accuracy <= 80) {
                    $currentLearnPace = 4;
                } else if ($accuracy < 100) {
                    $currentLearnPace = 5;
                } else {
                    $currentLearnPace = 6;
                }
            }

            // 更新学习进度
            if ($learn && $currentLearnPace > $learnPace) {
                $learn->learnPace = $currentLearnPace;
                $learn->save();
            }

            Db::commit();
            return $result;
        } catch (Exception|PDOException|ValidateException $e) {
            Db::rollback();
            $this->setError($e->getMessage());
            return false;
        }
    }

}